package rstplus;

/*
 * RST - Russian SMS transliterator
 * Copyleft 2011
 * Author: Alexey Shat'ko (Алексей Шатько), rstapp@yandex.ru
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this source code (in file copying.txt); if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


public final class TranslitAlgorithm {

    private static boolean omitSoftSign = false;
    private static boolean useX = false;
    private static boolean use4 = false;

    public static boolean isSoftSignOmited() {
        return omitSoftSign;
    }

    public static void setSoftSignOmited(boolean value) {
        omitSoftSign = value;
    }

    public static boolean isXUsed() {
        return useX;
    }

    public static void setXUsed(boolean value) {
        useX = value;
    }

    public static boolean is4Used() {
        return use4;
    }

    public static void set4Used(boolean value) {
        use4 = value;
    }

    private TranslitAlgorithm() {
    }

    public static String transliterate(String str) {
        int len = str.length();
        StringBuffer resultBuffer = new StringBuffer(len + len / 4);
        if (len == 0) {
            return "";
        } else if (len == 1) {
            processCharacter(str.charAt(0), NO_CHAR, NO_CHAR, resultBuffer);
            return resultBuffer.toString().trim();
        }
        char ch1 = NO_CHAR;
        char ch2 = str.charAt(0);
        char ch3 = str.charAt(1);
        int i = 1;
        while (true) {
            processCharacter(ch2, ch1, ch3, resultBuffer);
            if (i >= len) {
                return resultBuffer.toString().trim();
            }
            ch1 = ch2;
            ch2 = ch3;
            i++;
            ch3 = (i >= len) ? NO_CHAR : str.charAt(i);
        }
    }

    private static void processCharacter(char ch, char prevChar, char nextChar, StringBuffer buffer) {
        int chType = SMSSender.getCharType(ch);
        switch (chType) {
            case SMSSender.ONE_BYTE_CHAR:
            case SMSSender.TWO_BYTE_CHAR:
                buffer.append(ch);
                return;
            default:
                break;
        }
        switch (ch) {
            case '№':
                buffer.append('#');
                break;
            case 'А':
                buffer.append('A');
                break;
            case 'Б':
                buffer.append('B');
                break;
            case 'В':
                buffer.append('V');
                break;
            case 'Г':
                buffer.append('G');
                break;
            case 'Д':
                buffer.append('D');
                break;
            case 'Е':
                buffer.append('E');
                break;
            case 'Ё':
                if (isRussianCapital(nextChar)
                        || (isRussianCapital(prevChar) && !isRussian(nextChar))) {
                    buffer.append('Y');
                    buffer.append('O');
                } else {
                    buffer.append('Y');
                    buffer.append('o');
                }
                break;
            case 'Ж':
                if (isRussianCapital(nextChar)
                        || (isRussianCapital(prevChar) && !isRussian(nextChar))) {
                    buffer.append('Z');
                    buffer.append('H');

                } else {
                    buffer.append('Z');
                    buffer.append('h');
                }
                break;
            case 'З':
                buffer.append('Z');
                break;
            case 'И':
                buffer.append('I');
                break;
            case 'Й':
                buffer.append('J');
                break;
            case 'К':
                if (useX) {
                    if ((nextChar == 'с') || (nextChar == 'С')) {
                        buffer.append('X');
                        break;
                    }
                }
                buffer.append('K');
                break;
            case 'Л':
                buffer.append('L');
                break;
            case 'М':
                buffer.append('M');
                break;
            case 'Н':
                buffer.append('N');
                break;
            case 'О':
                buffer.append('O');
                break;
            case 'П':
                buffer.append('P');
                break;
            case 'Р':
                buffer.append('R');
                break;
            case 'С':
                if (useX) {
                    if (prevChar == 'К') {
                        break;
                    }
                }
                buffer.append('S');
                break;
            case 'Т':
                buffer.append('T');
                break;
            case 'У':
                buffer.append('U');
                break;
            case 'Ф':
                buffer.append('F');
                break;
            case 'Х':
                buffer.append('H');
                break;
            case 'Ц':
                buffer.append('C');
                break;
            case 'Ч':
                if (use4) {
                    buffer.append('4');
                } else if (isRussianCapital(nextChar)
                        || (isRussianCapital(prevChar) && !isRussian(nextChar))) {
                    buffer.append('C');
                    buffer.append('H');
                } else {
                    buffer.append('C');
                    buffer.append('h');
                }
                break;
            case 'Ш':
                if (isRussianCapital(nextChar)
                        || (isRussianCapital(prevChar) && !isRussian(nextChar))) {
                    buffer.append('S');
                    buffer.append('H');
                } else {
                    buffer.append('S');
                    buffer.append('h');
                }
                break;
            case 'Щ':
                if (isRussianCapital(nextChar)
                        || (isRussianCapital(prevChar) && !isRussian(nextChar))) {
                    buffer.append('S');
                    buffer.append('C');
                    buffer.append('H');
                } else {
                    buffer.append('S');
                    buffer.append('c');
                    buffer.append('h');
                }
                break;
            case 'Ъ':
            case 'Ь':
            case 'ъ':
            case 'ь':
                if (!omitSoftSign) {
                    buffer.append('\'');
                }
                break;
            case 'Ы':
                buffer.append('Y');
                break;
            case 'Э':
                buffer.append('E');
                break;
            case 'Ю':
                if (isRussianCapital(nextChar)
                        || (isRussianCapital(prevChar) && !isRussian(nextChar))) {
                    buffer.append('Y');
                    buffer.append('U');
                } else {
                    buffer.append('Y');
                    buffer.append('u');
                }
                break;
            case 'Я':
                if (isRussianCapital(nextChar)
                        || (isRussianCapital(prevChar) && !isRussian(nextChar))) {
                    buffer.append('Y');
                    buffer.append('A');
                } else {
                    buffer.append('Y');
                    buffer.append('a');
                }
                break;
            case 'а':
                buffer.append('a');
                break;
            case 'б':
                buffer.append('b');
                break;
            case 'в':
                buffer.append('v');
                break;
            case 'г':
                buffer.append('g');
                break;
            case 'д':
                buffer.append('d');
                break;
            case 'е':
                buffer.append('e');
                break;
            case 'ё':
                buffer.append('y');
                buffer.append('o');
                break;
            case 'ж':
                buffer.append('z');
                buffer.append('h');
                break;
            case 'з':
                buffer.append('z');
                break;
            case 'и':
                buffer.append('i');
                break;
            case 'й':
                buffer.append('j');
                break;
            case 'к':
                if (useX) {
                    if (nextChar == 'с') {
                        buffer.append('x');
                        break;
                    }
                }
                buffer.append('k');
                break;
            case 'л':
                buffer.append('l');
                break;
            case 'м':
                buffer.append('m');
                break;
            case 'н':
                buffer.append('n');
                break;
            case 'о':
                buffer.append('o');
                break;
            case 'п':
                buffer.append('p');
                break;
            case 'р':
                buffer.append('r');
                break;
            case 'с':
                if (useX) {
                    if ((prevChar == 'К') || (prevChar == 'к')) {
                        break;
                    }
                }
                buffer.append('s');
                break;
            case 'т':
                buffer.append('t');
                break;
            case 'у':
                buffer.append('u');
                break;
            case 'ф':
                buffer.append('f');
                break;
            case 'х':
                buffer.append('h');
                break;
            case 'ц':
                buffer.append('c');
                break;
            case 'ч':
                if (use4) {
                    buffer.append('4');
                } else {
                    buffer.append('c');
                    buffer.append('h');
                }
                break;
            case 'ш':
                buffer.append('s');
                buffer.append('h');
                break;
            case 'щ':
                buffer.append('s');
                buffer.append('c');
                buffer.append('h');
                break;
            case 'ы':
                buffer.append('y');
                break;
            case 'э':
                buffer.append('e');
                break;
            case 'ю':
                buffer.append('y');
                buffer.append('u');
                break;
            case 'я':
                buffer.append('y');
                buffer.append('a');
                break;
            default:
                buffer.append('~');
                break;
        }
    }
    private static final char NO_CHAR = ' ';

    private static boolean isRussianSmall(char ch) {
        return ((ch >= 'а') && (ch <= 'я')) || (ch == 'ё');
    }

    private static boolean isRussianCapital(char ch) {
        return ((ch >= 'А') && (ch <= 'Я')) || (ch == 'Ё');
    }

    private static boolean isRussian(char ch) {
        return ((ch >= 'а') && (ch <= 'я')) || ((ch >= 'А') && (ch <= 'Я')) || (ch == 'ё') || (ch == 'Ё');
    }
}
